package com.vertx.starter;

import io.vertx.core.*;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.eventbus.Message;
import io.vertx.core.eventbus.MessageConsumer;
import lombok.extern.log4j.Log4j2;

@Log4j2
public abstract class AppVerticle extends AbstractVerticle implements AppVerticalDeployAgent, AppMessageSenderAgent {

    public static int DEFAULT_SEND_TIMEOUT = 30000;
    private AppVerticalDeployAgent deployAgent;
    private AppMessageSenderAgent senderAgent;

    public AppVerticle() {
    }

    public void init(Vertx vertx, Context context) {
        super.init(vertx, context);
        this.deployAgent = AppVerticalDeployAgent.create(vertx);
        this.senderAgent = AppMessageSenderAgent.create(vertx);
    }

    public <T extends AppVerticle> Future<String> deployVerticle(Class<T> clazz) {
        return this.deployAgent.deployVerticle(clazz);
    }

    public <T extends AppVerticle> Future<String> deployVerticle(Class<T> clazz, DeploymentOptions options) {
        return this.deployAgent.deployVerticle(clazz, options);
    }

    public void sendMessage(String address, Object payload) {
        this.senderAgent.sendMessage(address, payload, this.createOrWrapDeliveryOption((DeliveryOptions) null));
    }

    public void sendMessage(String address, Object payload, DeliveryOptions options) {
        this.senderAgent.sendMessage(address, payload, this.createOrWrapDeliveryOption(options));
    }

    public void publishMessage(String address, Object payload) {
        this.senderAgent.publishMessage(address, payload, this.createOrWrapDeliveryOption((DeliveryOptions) null));
    }

    public void publishMessage(String address, Object payload, DeliveryOptions options) {
        this.senderAgent.publishMessage(address, payload, this.createOrWrapDeliveryOption(options));
    }

    public <T> Future<Message<T>> requestMessage(String address, Object payload) {
        return this.senderAgent.requestMessage(address, payload, this.createOrWrapDeliveryOption((DeliveryOptions) null));
    }

    public <T> Future<Message<T>> requestMessage(String address, Object payload, DeliveryOptions options) {
        return this.senderAgent.requestMessage(address, payload, this.createOrWrapDeliveryOption(options));
    }

    public <T> MessageConsumer<T> messageConsumer(String address, Handler<Message<T>> handler) {
        return this.senderAgent.messageConsumer(address, handler);
    }

    public <T> MessageConsumer<T> messageLocalConsumer(String address, Handler<Message<T>> handler) {
        return this.senderAgent.messageLocalConsumer(address, handler);
    }

    private DeliveryOptions createOrWrapDeliveryOption(DeliveryOptions options) {
        if (options != null) {
            if (options.getSendTimeout() == 30000L) {
                options.setSendTimeout((long) DEFAULT_SEND_TIMEOUT);
            }

            return options;
        } else {
            options = new DeliveryOptions();
            options.setSendTimeout((long) DEFAULT_SEND_TIMEOUT);
            return options;
        }
    }
}